#ifndef HOST_H
#define HOST_H

#include <Windows.h>
#include "commdef.h"

/*
 *	PubKey
 */
class PubKey
{
public:
	PubKey( void );
	~PubKey();

	void Set( BYTE* key, int len, int e, int capa );
	void UnSet( void );
	const BYTE* GetKey(){ return _key; }
	int GetKeyLen(){ return _keyLen; }
	int GetExponent(){ return _e; }
	bool KeyBlob( BYTE* blob, int maxLen, int* len );
	int GetKeyBlobLen(){ return _keyLen + 8 + 12; }
	void SetByBlob( BYTE* blob, int capa );
	int GetCapa(){ return _capa; }

protected:
	BYTE*	_key;
	int		_keyLen;
	int		_e;
	int		_capa;
};

/*
 *	HostSub
 */
struct HostSub
{
	char	userName[MAX_NAMEBUF];
	char	hostName[MAX_NAMEBUF];
	ULONG	addr;
	int		portNum;
};

/*
 *	Host
 */
struct Host
{
	HostSub	hostSub;
	char	nickName[MAX_NAMEBUF];
	char	groupName[MAX_NAMEBUF];
	ULONG	hostStatus;
	time_t	updateTime;
	int		priority;
	int		refCnt;
	PubKey	pubKey;
	int		cryptSpec;

	Host() : refCnt(0){}
	~Host(){ refCnt = 0; }
	int RefCnt( int cnt = 0 ){ return refCnt += cnt; }
};

/*
 *	THosts
 */
class THosts
{
public:
	enum Kind{ NAME, ADDR, NAME_ADDR, MAX_ARRAY };
	bool _enable[MAX_ARRAY];

	THosts( void );
	~THosts();

	void Enable( Kind kind, bool enable ){ _enable[kind] = enable; }
	bool AddHost( Host* host );
	bool DelHost( Host* host );
	int  GetHostCnt(){ return _hostCnt; }
	Host* GetHost( int index, Kind kind = NAME ){ return _hosts[kind][index]; }
	Host* GetHostByName( HostSub* hostSub ){ return _enable[NAME] ? Search( NAME, hostSub ) : NULL; }
	Host* GetHostByAddr( HostSub* hostSub ){ return _enable[ADDR] ? Search( ADDR, hostSub ) : NULL; }
	Host* GetHostByNameAddr( HostSub* hostSub ){ return _enable[NAME_ADDR] ? Search( NAME_ADDR, hostSub) : NULL;}
	int   PriorityHostCnt( int priority, int range = 1 );

protected:
	Host* Search( Kind kind, HostSub* hostSub, int* insertIndex = NULL );
	int	Cmp( HostSub* hostSub1, HostSub* hostSub2, Kind kind );

protected:
	int		_hostCnt;
	Host**	_hosts[MAX_ARRAY];
};

/*
 *	SendEntry
 */
enum SendStatus { ST_GETCRYPT, ST_MAKECRYPTMSG, ST_MAKEMSG, ST_SENDMSG, ST_DONE };
class SendEntry
{
public:
	SendEntry() : _msg( NULL ), _host( NULL ){}
	~SendEntry(){ delete[] _msg; if( _host && _host->RefCnt(-1) == 0 ) delete _host; }
	void SetMsg( char* msg, int len ){ delete[] _msg; _msg = new char[_msgLen=len]; memcpy( _msg, msg, len ); }
	const char* GetMsg(){ return _msg; }
	int GetMsgLen(){ return _msgLen; }
	void SetHost( Host* host ){ (_host = host)->RefCnt(1); }
	Host* GetHost(){ return _host; }
	void SetStatus( SendStatus status ){ _status = status; }
	SendStatus GetStatus(){ return _status; }
	void SetCommand( UINT command ){ _command = command; }
	UINT GetCommand(){ return _command; }
private:
	Host*		_host;
	SendStatus	_status;
	UINT		_command;
	char*		_msg;
	int			_msgLen;
};

bool IsSameHost( HostSub *hostSub1, HostSub *hostSub2 );

inline bool IsSameHostEx( HostSub *host, HostSub *host2 ) 
{ 
	return IsSameHost( host, host2 ) && host->addr == host2->addr && host->portNum == host2->portNum ? true : false;
}

#endif	// HOST_H